home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Add-Ons / MPW / MPW re2c 1.1 / doc / re2c.txt < prev    next >
Encoding:
Text File  |  1995-12-06  |  17.3 KB  |  519 lines  |  [TEXT/MPS ]

  1. NAME
  2.      re2c - convert regular expressions to C/C++
  3.  
  4.  
  5. SYNOPSIS
  6.      re2c [-esb] name
  7.  
  8.  
  9. DESCRIPTION
  10.      re2c is a preprocessor that generates C-based  recognizers  from  regular
  11.      expressions.  The input to re2c consists of C/C++ source interleaved with
  12.      comments of the form /*!re2c ... */ which contain scanner specifications.
  13.      In  the output these comments are replaced with code that, when executed,
  14.      will find the next input token and then execute some user-supplied token-
  15.      specific code.
  16.  
  17.      For example, given the following code
  18.  
  19.         #define NULL            ((char*) 0)
  20.         char *scan(char *p){
  21.         char *q;
  22.         #define YYCTYPE         char
  23.         #define YYCURSOR        p
  24.         #define YYLIMIT         p
  25.         #define YYMARKER        q
  26.         #define YYFILL(n)
  27.         /*!re2c
  28.                 [0-9]+          {return YYCURSOR;}
  29.                 [\000-\377]     {return NULL;}
  30.         */
  31.         }
  32.  
  33.      re2c will generate
  34.  
  35.         /* Generated by re2c on Sat Apr 16 11:40:58 1994 */
  36.         #line 1 "simple.re"
  37.         #define NULL            ((char*) 0)
  38.         char *scan(char *p){
  39.         char *q;
  40.         #define YYCTYPE         char
  41.         #define YYCURSOR        p
  42.         #define YYLIMIT         p
  43.         #define YYMARKER        q
  44.         #define YYFILL(n)
  45.         {
  46.                 YYCTYPE yych;
  47.                 unsigned int yyaccept;
  48.                 goto yy0;
  49.         yy1:    ++YYCURSOR;
  50.         yy0:
  51.                 if((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
  52.                 yych = *YYCURSOR;
  53.                 if(yych <= '/') goto yy4;
  54.                 if(yych >= ':') goto yy4;
  55.         yy2:    yych = *++YYCURSOR;
  56.                 goto yy7;
  57.  
  58.  
  59.  
  60.         yy3:
  61.         #line 10
  62.                 {return YYCURSOR;}
  63.         yy4:    yych = *++YYCURSOR;
  64.         yy5:
  65.         #line 11
  66.                 {return NULL;}
  67.         yy6:    ++YYCURSOR;
  68.                 if(YYLIMIT == YYCURSOR) YYFILL(1);
  69.                 yych = *YYCURSOR;
  70.         yy7:    if(yych <= '/') goto yy3;
  71.                 if(yych <= '9') goto yy6;
  72.                 goto yy3;
  73.         }
  74.         #line 12
  75.  
  76.         }
  77.  
  78.  
  79. OPTIONS
  80.      re2c provides the following options:
  81.  
  82.      -e   Cross-compile from an ASCII platform to an EBCDIC one.
  83.  
  84.      -s   Generate nested ifs for some switches.   Many  compilers  need  this
  85.           assist to generate better code.
  86.  
  87.      -b   Implies -s.  Use bit vectors as well in the attempt to  coax  better
  88.           code  out of the compiler.  Most useful for specifications with more
  89.           than a few keywords (e.g. for most programming languages).
  90.  
  91.  
  92. INTERFACE CODE
  93.      Unlike  other  scanner  generators,  re2c  does  not  generate   complete
  94.      scanners:   the user must supply some interface code.  In particular, the
  95.      user must define the following macros:
  96.  
  97.      YYCHAR
  98.           Type used to hold an input symbol.  Usually char or unsigned char.
  99.  
  100.      YYCURSOR
  101.           l-expression of type  *YYCHAR  that  points  to  the  current  input
  102.           symbol.   The  generated  code  advances  YYCURSOR  as  symbols  are
  103.           matched.  On entry, YYCURSOR  is  assumed  to  point  to  the  first
  104.           character of the current token.  On exit, YYCURSOR will point to the
  105.           first character of the following token.
  106.  
  107.      YLIMIT
  108.           Expression of  type  *YYCHAR  that  marks  the  end  of  the  buffer
  109.           (YLIMIT[-1]  is  the  last  character in the buffer).  The generated
  110.           code repeatedly compares YYCURSOR to YLIMIT to  determine  when  the
  111.           buffer needs (re)filling.
  112.  
  113.      YYMARKER
  114.           l-expression of type *YYCHAR.  The generated code saves backtracking
  115.           information in YYMARKER.
  116.  
  117.  
  118.  
  119.      YYFILL(n)
  120.           The generated code "calls" YYFILL when the buffer needs (re)filling:
  121.           at  least n additional characters should be provided.  YYFILL should
  122.           adjust YYCURSOR, YYLIMIT and YYMARKER  as  needed.   Note  that  for
  123.           typical  programming  languages  n will be the length of the longest
  124.           keyword plus one.
  125.  
  126.  
  127. SCANNER SPECIFICATIONS
  128.      Each  scanner  specification  consists  of  a  set  of  rules  and   name
  129.      definitions.  Rules consist of a regular expression along with a block of
  130.      C/C++ code that is to be executed when the associated regular  expression
  131.      is   matched.   Name  definitions  are  of  the  form  ``name  =  regular
  132.      expression;''.
  133.  
  134.  
  135. SUMMARY OF RE2C REGULAR EXPRESSIONS
  136.  
  137.      "foo"
  138.           the literal string foo.  ANSI-C escape sequences can be used.
  139.  
  140.      [xyz]
  141.           a "character class"; in this case, the  regular  expression  matches
  142.           either an 'x', a 'y', or a 'z'.
  143.  
  144.      [abj-oZ]
  145.           a "character class" with a range in it; matches an 'a', a  'b',  any
  146.           letter from 'j' through 'o', or a 'Z'.
  147.  
  148.      r\s  match any r which isn't an s. r and s must  be  regular  expressions
  149.           which can be expressed as character classes.
  150.  
  151.      r*   zero or more r's, where r is any regular expression
  152.  
  153.      r+   one or more r's
  154.  
  155.      r?   zero or one r's (that is, "an optional r")
  156.  
  157.      name the expansion of the "name" definition (see above)
  158.  
  159.      (r)  an r; parentheses are used to override precedence (see below)
  160.  
  161.      rs   an r followed by an s ("concatenation")
  162.  
  163.      r|s  either an r or an s
  164.  
  165.      r/s  an r but only if it is followed by an s. The s is not  part  of  the
  166.           matched  text.  This  type of regular expression is called "trailing
  167.           context".
  168.  
  169.      The regular expressions listed above are grouped according to precedence,
  170.      from  highest  precedence  at  the  top  to  lowest at the bottom.  Those
  171.      grouped together have equal precedence.
  172.  
  173.  
  174.  
  175. A LARGER EXAMPLE
  176.  
  177.         #include <stdlib.h>
  178.         #include <stdio.h>
  179.         #include <fcntl.h>
  180.         #include <string.h>
  181.  
  182.         #define ADDEQ   257
  183.         #define ANDAND  258
  184.         #define ANDEQ   259
  185.         #define ARRAY   260
  186.         #define ASM     261
  187.         #define AUTO    262
  188.         #define BREAK   263
  189.         #define CASE    264
  190.         #define CHAR    265
  191.         #define CONST   266
  192.         #define CONTINUE        267
  193.         #define DECR    268
  194.         #define DEFAULT 269
  195.         #define DEREF   270
  196.         #define DIVEQ   271
  197.         #define DO      272
  198.         #define DOUBLE  273
  199.         #define ELLIPSIS        274
  200.         #define ELSE    275
  201.         #define ENUM    276
  202.         #define EQL     277
  203.         #define EXTERN  278
  204.         #define FCON    279
  205.         #define FLOAT   280
  206.         #define FOR     281
  207.         #define FUNCTION        282
  208.         #define GEQ     283
  209.         #define GOTO    284
  210.         #define ICON    285
  211.         #define ID      286
  212.         #define IF      287
  213.         #define INCR    288
  214.         #define INT     289
  215.         #define LEQ     290
  216.         #define LONG    291
  217.         #define LSHIFT  292
  218.         #define LSHIFTEQ        293
  219.         #define MODEQ   294
  220.         #define MULEQ   295
  221.         #define NEQ     296
  222.         #define OREQ    297
  223.         #define OROR    298
  224.         #define POINTER 299
  225.         #define REGISTER        300
  226.         #define RETURN  301
  227.         #define RSHIFT  302
  228.         #define RSHIFTEQ        303
  229.         #define SCON    304
  230.         #define SHORT   305
  231.  
  232.  
  233.  
  234.         #define SIGNED  306
  235.         #define SIZEOF  307
  236.         #define STATIC  308
  237.         #define STRUCT  309
  238.         #define SUBEQ   310
  239.         #define SWITCH  311
  240.         #define TYPEDEF 312
  241.         #define UNION   313
  242.         #define UNSIGNED        314
  243.         #define VOID    315
  244.         #define VOLATILE        316
  245.         #define WHILE   317
  246.         #define XOREQ   318
  247.         #define EOI     319
  248.  
  249.         typedef unsigned int uint;
  250.         typedef unsigned char uchar;
  251.  
  252.         #define BSIZE   8192
  253.  
  254.         #define YYCTYPE         uchar
  255.         #define YYCURSOR        cursor
  256.         #define YYLIMIT         s->lim
  257.         #define YYMARKER        s->ptr
  258.         #define YYFILL(n)       {cursor = fill(s, cursor);}
  259.  
  260.         #define RET(i)  {s->cur = cursor; return i;}
  261.  
  262.         typedef struct Scanner {
  263.             int                 fd;
  264.             uchar               *bot, *tok,  *ptr,  *cur,  *pos,  *lim,  *top,
  265.         *eof;
  266.             uint                line;
  267.         } Scanner;
  268.  
  269.         uchar *fill(Scanner *s, uchar *cursor){
  270.             if(!s->eof){
  271.                 uint cnt = s->tok - s->bot;
  272.                 if(cnt){
  273.                     memcpy(s->bot, s->tok, s->lim - s->tok);
  274.                     s->tok = s->bot;
  275.                     s->ptr -= cnt;
  276.                     cursor -= cnt;
  277.                     s->pos -= cnt;
  278.                     s->lim -= cnt;
  279.                 }
  280.                 if((s->top - s->lim) < BSIZE){
  281.                     uchar *buf = (uchar*)
  282.                         malloc(((s->lim - s->bot) + BSIZE)*sizeof(uchar));
  283.                     memcpy(buf, s->tok, s->lim - s->tok);
  284.                     s->tok = buf;
  285.                     s->ptr = &buf[s->ptr - s->bot];
  286.                     cursor = &buf[cursor - s->bot];
  287.                     s->pos = &buf[s->pos - s->bot];
  288.                     s->lim = &buf[s->lim - s->bot];
  289.                     s->top = &s->lim[BSIZE];
  290.  
  291.  
  292.  
  293.                     free(s->bot);
  294.                     s->bot = buf;
  295.                 }
  296.                 if((cnt = read(s->fd, (char*) s->lim, BSIZE)) != BSIZE){
  297.                     s->eof = &s->lim[cnt]; *(s->eof)++ = '\n';
  298.                 }
  299.                 s->lim += cnt;
  300.             }
  301.             return cursor;
  302.         }
  303.  
  304.         int scan(Scanner *s){
  305.                 uchar *cursor = s->cur;
  306.         std:
  307.                 s->tok = cursor;
  308.         /*!re2c
  309.         any     = [\000-\377];
  310.         O       = [0-7];
  311.         D       = [0-9];
  312.         L       = [a-zA-Z_];
  313.         H       = [a-fA-F0-9];
  314.         E       = [Ee] [+-]? D+;
  315.         FS      = [fFlL];
  316.         IS      = [uUlL]*;
  317.         ESC     = [\\] ([abfnrtv?'"\\] | "x" H+ | O+);
  318.         */
  319.  
  320.         /*!re2c
  321.                 "/*"                    { goto comment; }
  322.  
  323.                 "auto"                  { RET(AUTO); }
  324.                 "break"                 { RET(BREAK); }
  325.                 "case"                  { RET(CASE); }
  326.                 "char"                  { RET(CHAR); }
  327.                 "const"                 { RET(CONST); }
  328.                 "continue"              { RET(CONTINUE); }
  329.                 "default"               { RET(DEFAULT); }
  330.                 "do"                    { RET(DO); }
  331.                 "double"                { RET(DOUBLE); }
  332.                 "else"                  { RET(ELSE); }
  333.                 "enum"                  { RET(ENUM); }
  334.                 "extern"                { RET(EXTERN); }
  335.                 "float"                 { RET(FLOAT); }
  336.                 "for"                   { RET(FOR); }
  337.                 "goto"                  { RET(GOTO); }
  338.                 "if"                    { RET(IF); }
  339.                 "int"                   { RET(INT); }
  340.                 "long"                  { RET(LONG); }
  341.                 "register"              { RET(REGISTER); }
  342.                 "return"                { RET(RETURN); }
  343.                 "short"                 { RET(SHORT); }
  344.                 "signed"                { RET(SIGNED); }
  345.                 "sizeof"                { RET(SIZEOF); }
  346.                 "static"                { RET(STATIC); }
  347.                 "struct"                { RET(STRUCT); }
  348.                 "switch"                { RET(SWITCH); }
  349.  
  350.  
  351.  
  352.                 "typedef"               { RET(TYPEDEF); }
  353.                 "union"                 { RET(UNION); }
  354.                 "unsigned"              { RET(UNSIGNED); }
  355.                 "void"                  { RET(VOID); }
  356.                 "volatile"              { RET(VOLATILE); }
  357.                 "while"                 { RET(WHILE); }
  358.  
  359.                 L (L|D)*                { RET(ID); }
  360.  
  361.                 ("0" [xX] H+ IS?) | ("0" D+ IS?) | (D+ IS?) |
  362.                 (['] (ESC|any\[\n\\'])* ['])
  363.                                         { RET(ICON); }
  364.  
  365.                 (D+ E FS?) | (D* "." D+ E? FS?) | (D+ "." D* E? FS?)
  366.                                         { RET(FCON); }
  367.  
  368.                 (["] (ESC|any\[\n\\"])* ["])
  369.                                         { RET(SCON); }
  370.  
  371.                 "..."                   { RET(ELLIPSIS); }
  372.                 ">>="                   { RET(RSHIFTEQ); }
  373.                 "<<="                   { RET(LSHIFTEQ); }
  374.                 "+="                    { RET(ADDEQ); }
  375.                 "-="                    { RET(SUBEQ); }
  376.                 "*="                    { RET(MULEQ); }
  377.                 "/="                    { RET(DIVEQ); }
  378.                 "%="                    { RET(MODEQ); }
  379.                 "&="                    { RET(ANDEQ); }
  380.                 "^="                    { RET(XOREQ); }
  381.                 "|="                    { RET(OREQ); }
  382.                 ">>"                    { RET(RSHIFT); }
  383.                 "<<"                    { RET(LSHIFT); }
  384.                 "++"                    { RET(INCR); }
  385.                 "--"                    { RET(DECR); }
  386.                 "->"                    { RET(DEREF); }
  387.                 "&&"                    { RET(ANDAND); }
  388.                 "||"                    { RET(OROR); }
  389.                 "<="                    { RET(LEQ); }
  390.                 ">="                    { RET(GEQ); }
  391.                 "=="                    { RET(EQL); }
  392.                 "!="                    { RET(NEQ); }
  393.                 ";"                     { RET(';'); }
  394.                 "{"                     { RET('{'); }
  395.                 "}"                     { RET('}'); }
  396.                 ","                     { RET(','); }
  397.                 ":"                     { RET(':'); }
  398.                 "="                     { RET('='); }
  399.                 "("                     { RET('('); }
  400.                 ")"                     { RET(')'); }
  401.                 "["                     { RET('['); }
  402.                 "]"                     { RET(']'); }
  403.                 "."                     { RET('.'); }
  404.                 "&"                     { RET('&'); }
  405.                 "!"                     { RET('!'); }
  406.                 "~"                     { RET('~'); }
  407.                 "-"                     { RET('-'); }
  408.  
  409.  
  410.  
  411.                 "+"                     { RET('+'); }
  412.                 "*"                     { RET('*'); }
  413.                 "/"                     { RET('/'); }
  414.                 "%"                     { RET('%'); }
  415.                 "<"                     { RET('<'); }
  416.                 ">"                     { RET('>'); }
  417.                 "^"                     { RET('^'); }
  418.                 "|"                     { RET('|'); }
  419.                 "?"                     { RET('?'); }
  420.  
  421.  
  422.                 [ \t\v\f]+           { goto std; }
  423.  
  424.                 "\n"
  425.                     {
  426.                         if(cursor == s->eof) RET(EOI);
  427.                         s->pos = cursor; s->line++;
  428.                         goto std;
  429.                     }
  430.  
  431.                 any
  432.                     {
  433.                         printf("unexpected character: %c\n", *s->tok);
  434.                         goto std;
  435.                     }
  436.         */
  437.  
  438.         comment:
  439.         /*!re2c
  440.                 "*/"                    { goto std; }
  441.                 "\n"
  442.                     {
  443.                         if(cursor == s->eof) RET(EOI);
  444.                         s->tok = s->pos = cursor; s->line++;
  445.                         goto comment;
  446.                     }
  447.                 any                     { goto comment; }
  448.         */
  449.         }
  450.  
  451.         main(){
  452.             Scanner in;
  453.             int t;
  454.             memset((char*) &in, 0, sizeof(in));
  455.             in.fd = 0;
  456.             while((t = scan(&in)) != EOI){
  457.         /*
  458.                 printf("%d\t%.*s\n", t, in.cur - in.tok, in.tok);
  459.                 printf("%d\n", t);
  460.         */
  461.             }
  462.             close(in.fd);
  463.         }
  464.  
  465.  
  466.  
  467. SEE ALSO
  468.  
  469.      flex(1), lex(1).
  470.  
  471.  
  472. FEATURES
  473.  
  474.      re2c does not provide a default action:  the generated code assumes  that
  475.      the  input  will  consist of a sequence of tokens.  Typically this can be
  476.      dealt with by adding a rule such as the one for unexpected characters  in
  477.      the example above.
  478.  
  479.      The user must arrange for a sentinel token to appear at the end of  input
  480.      (and  provide  a rule for matching it):  re2c does not provide an <<EOF>>
  481.      expression.  If the source is from a null-byte terminated string, a  rule
  482.      matching  a  null  character  will suffice.  If the source is from a file
  483.      then the approach taken in the example can be used: pad the input with  a
  484.      newline (or some other character that can't appear within another token);
  485.      upon recognizing such a character check to see if it is the sentinel  and
  486.      act accordingly.
  487.  
  488.      re2c  does  not  provide  start  conditions:   use  a  separate   scanner
  489.      specification  for  each  start  condition  (as  illustrated in the above
  490.      example).
  491.  
  492.      No [^x].  Use difference instead.
  493.  
  494. BUGS
  495.  
  496.      Only fixed length trailing context can be handled.
  497.  
  498.      The maximum value appearing as a parameter n to YYFILL is not provided to
  499.      the  generated  code (this value is needed for constructing the interface
  500.      code).  Note that this value is usually  relatively  small:  for  typical
  501.      programming  languages  n  will be the length of the longest keyword plus
  502.      one.
  503.  
  504.      Difference only works for character sets.
  505.  
  506.      The re2c internal algorithms need documentation.
  507.  
  508.  
  509. AUTHOR
  510.  
  511.      Please send bug reports, fixes and feedback to:
  512.  
  513.      Peter Bumbulis
  514.      Computer Systems Group
  515.      University of Waterloo
  516.      Waterloo, Ontario
  517.      N2L 3G1
  518.      Internet:  peter@csg.uwaterloo.ca
  519.